Understanding Maps in Go 您所在的位置:网站首页 golang map struct key Understanding Maps in Go

Understanding Maps in Go

2024-04-05 19:25| 来源: 网络整理| 查看: 265

Tutorial Series: How To Code in Go1/53 How To Code in Go eBook 2/53 How To Install Go and Set Up a Local Programming Environment on Ubuntu 18.04 3/53 How To Install Go and Set Up a Local Programming Environment on macOS 4/53 How To Install Go and Set Up a Local Programming Environment on Windows 10 5/53 How To Write Your First Program in Go 6/53 Understanding the GOPATH 7/53 How To Write Comments in Go 8/53 Understanding Data Types in Go 9/53 An Introduction to Working with Strings in Go 10/53 How To Format Strings in Go 11/53 An Introduction to the Strings Package in Go 12/53 How To Use Variables and Constants in Go 13/53 How To Convert Data Types in Go 14/53 How To Do Math in Go with Operators 15/53 Understanding Boolean Logic in Go 16/53 Understanding Maps in Go 17/53 Understanding Arrays and Slices in Go 18/53 Handling Errors in Go 19/53 Creating Custom Errors in Go 20/53 Handling Panics in Go 21/53 Importing Packages in Go 22/53 How To Write Packages in Go 23/53 Understanding Package Visibility in Go 24/53 How To Write Conditional Statements in Go 25/53 How To Write Switch Statements in Go 26/53 How To Construct For Loops in Go 27/53 Using Break and Continue Statements When Working with Loops in Go 28/53 How To Define and Call Functions in Go 29/53 How To Use Variadic Functions in Go 30/53 Understanding defer in Go 31/53 Understanding init in Go 32/53 Customizing Go Binaries with Build Tags 33/53 Understanding Pointers in Go 34/53 Defining Structs in Go 35/53 Defining Methods in Go 36/53 How To Build and Install Go Programs 37/53 How To Use Struct Tags in Go 38/53 How To Use Interfaces in Go 39/53 Building Go Applications for Different Operating Systems and Architectures 40/53 Using ldflags to Set Version Information for Go Applications 41/53 How To Use the Flag Package in Go 42/53 How to Use Go Modules 43/53 How to Distribute Go Modules 44/53 How to Use a Private Go Module in Your Own Project 45/53 How To Run Multiple Functions Concurrently in Go 46/53 How to Add Extra Information to Errors in Go 47/53 How To Use Dates and Times in Go 48/53 How To Use Contexts in Go 49/53 How To Use JSON in Go 50/53 How To Make an HTTP Server in Go 51/53 How To Make HTTP Requests in Go 52/53 How To Use Generics in Go 53/53 How To Use Templates in Go TutorialUnderstanding Maps in GoPublished on April 23, 2019GoDevelopmentDefault avatar

By Gopher Guides

EnglishUnderstanding Maps in Go

Most modern programming languages have the concept of a dictionary or a hash type. These types are commonly used to store data in pairs with a key that maps to a value.

In Go, the map data type is what most programmers would think of as the dictionary type. It maps keys to values, making key-value pairs that are a useful way to store data in Go. A map is constructed by using the keyword map followed by the key data type in square brackets [ ], followed by the value data type. The key-value pairs are then placed inside curly braces on either side { }:

map[key]value{}

You typically use maps in Go to hold related data, such as the information contained in an ID. A map with data looks like this:

map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}

In addition to the curly braces, there are also colons throughout the map that connect the key-value pairs. The words to the left of the colons are the keys. Keys can be any comparable type in Go, like strings, ints, and so on.

The keys in the example map are:

"name" "animal" "color" "location"

The words to the right of the colons are the values. Values can be any data type. The values in the example map are:

"Sammy" "shark" "blue" "ocean"

Like the other data types, you can store the map inside a variable, and print it out:

sammy := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"} fmt.Println(sammy)

This would be your output:

Outputmap[animal:shark color:blue location:ocean name:Sammy]

The order of the key-value pairs may have shifted. In Go, the map data type is unordered. Regardless of the order, the key-value pairs will remain intact, enabling you to access data based on their relational meaning.

Accessing Map Items

You can call the values of a map by referencing the related keys. Since maps offer key-value pairs for storing data, they can be important and useful items in your Go program.

If you want to isolate Sammy’s username, you can do so by calling sammy["name"]; the variable holding your map and the related key. Let’s print that out:

fmt.Println(sammy["name"])

And receive the value as output:

OutputSammy

Maps behave like a database; instead of calling an integer to get a particular index value as you would with a slice, you assign a value to a key and call that key to get its related value.

By invoking the key "name" you receive the value of that key, which is "Sammy".

Similarly you can call the remaining values in the sammy map using the same format:

fmt.Println(sammy["animal"]) // returns shark fmt.Println(sammy["color"]) // returns blue fmt.Println(sammy["location"]) // returns ocean

By making use of the key-value pairs in map data types, you can reference keys to retrieve values.

Keys and Values

Unlike some programming languages, Go does not have any convenience functions to list out the keys or values of a map. An example of this would be Python’s .keys() method for dictionaries. It does, however, allow for iteration by using the range operator:

for key, value := range sammy { fmt.Printf("%q is the key for the value %q\n", key, value) }

When ranging through a map in Go, it’ll return two values. The first value will be the key, and the second value will be the value. Go will create these variables with the correct data type. In this case, the map key was a string so key will also be a string. The value is also a string:

Output"animal" is the key for the value "shark" "color" is the key for the value "blue" "location" is the key for the value "ocean" "name" is the key for the value "Sammy"

To get a list of just the keys, you can use the range operator again. You can declare just one variable to only access the keys:

keys := []string{} for key := range sammy { keys = append(keys, key) } fmt.Printf("%q", keys)

The program begins by declaring a slice to store your keys in.

The output will show only the keys of your map:

Output["color" "location" "name" "animal"]

Again, the keys are not sorted. If you want to sort them, you use the sort.Strings function from the sort package:

sort.Strings(keys)

With this function, you’ll receive the following output:

Output["animal" "color" "location" "name"]

You can use the same pattern to retrieve just the values in a map. In the next example, you pre-allocate the slice to avoid allocations, thus making the program more efficient:

sammy := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"} items := make([]string, len(sammy)) var i int for _, v := range sammy { items[i] = v i++ } fmt.Printf("%q", items)

First you declare a slice to store your keys in; since you know how many items you need, you can avoid potential memory allocations by defining the slice at the exact same size. You then declare your index variable. As you don’t want the key, you use the _ operator, when starting your loop, to ignore the key’s value. Your output would be the following:

Output["ocean" "Sammy" "shark" "blue"]

To determine the number of items in a map, you can use the built-in len function:

sammy := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"} fmt.Println(len(sammy))

The output displays the number of items in your map:

Output4

Even though Go doesn’t ship with convenience functions to get keys and values, it only takes a few lines of code to retrieve the keys and values when needed.

Checking Existence

Maps in Go will return the zero value for the value type of the map when the requested key is missing. Because of this, you need an alternative way to differentiate a stored zero, versus a missing key.

Let’s look up a value in a map that you know doesn’t exist and look at the value returned:

counts := map[string]int{} fmt.Println(counts["sammy"])

You’ll see the following output:

Output0

Even though the key sammy was not in the map, Go still returned the value of 0. This is because the value data type is an int, and because Go has a zero value for all variables, it returns the zero value of 0.

In many cases, this is undesirable and would lead to a bug in your program. When looking up the value in a map, Go can return a second, optional value. This second value is a bool and will be true if the key was found, or false if the key was not found. In Go, this is referred to as the ok idiom. Even though you could name the variable that captures the second argument anything you want, in Go, you always name it ok:

count, ok := counts["sammy"]

If the key sammy exists in the counts map, then ok will be true. Otherwise ok will be false.

You can use the ok variable to decide what to do in your program:

if ok { fmt.Printf("Sammy has a count of %d\n", count) } else { fmt.Println("Sammy was not found") }

This would result in the following output:

OutputSammy was not found

In Go, you can combine variable declaration and conditional checking with an if/else block. This allows you to use a single statement for this check:

if count, ok := counts["sammy"]; ok { fmt.Printf("Sammy has a count of %d\n", count) } else { fmt.Println("Sammy was not found") }

When retrieving a value from a map in Go, it’s always good practice to check for its existence as well to avoid bugs in your program.

Modifying Maps

Maps are a mutable data structure, so you can modify them. Let’s look at adding and deleting map items in this section.

Adding and Changing Map Items

Without using a method or function, you can add key-value pairs to maps. You do this using the maps variable name, followed by the key value in square brackets [ ], and using the equal = operator to set a new value:

map[key] = value

In practice, you can see this work by adding a key-value pair to a map called usernames:

usernames := map[string]string{"Sammy": "sammy-shark", "Jamie": "mantisshrimp54"} usernames["Drew"] = "squidly" fmt.Println(usernames)

The output will display the new Drew:squidly key-value pair in the map:

Outputmap[Drew:squidly Jamie:mantisshrimp54 Sammy:sammy-shark]

Because maps are returned unordered, this pair may occur anywhere in the map output. If you use the usernames map later in your program file, it will include the additional key-value pair.

You can also use this syntax for modifying the value assigned to a key. In this case, you reference an existing key and pass a different value to it.

Consider a map called followers that tracks followers of users on a given network. The user "drew" had a bump in followers today, so you need to update the integer value passed to the "drew" key. You’ll use the Println() function to check that the map was modified:

followers := map[string]int{"drew": 305, "mary": 428, "cindy": 918} followers["drew"] = 342 fmt.Println(followers)

Your output will show the updated value for drew:

Outputmap[cindy:918 drew:342 mary:428]

You see that the number of followers jumped from the integer value of 305 to 342.

You can use this method for adding key-value pairs to maps with user input. Let’s write a quick program called usernames.go that runs on the command line and allows input from the user to add more names and associated usernames:

usernames.go package main import ( "fmt" "strings" ) func main() { usernames := map[string]string{"Sammy": "sammy-shark", "Jamie": "mantisshrimp54"} for { fmt.Println("Enter a name:") var name string _, err := fmt.Scanln(&name) if err != nil { panic(err) } name = strings.TrimSpace(name) if u, ok := usernames[name]; ok { fmt.Printf("%q is the username of %q\n", u, name) continue } fmt.Printf("I don't have %v's username, what is it?\n", name) var username string _, err = fmt.Scanln(&username) if err != nil { panic(err) } username = strings.TrimSpace(username) usernames[name] = username fmt.Println("Data updated.") } }

In usernames.go you first define the original map. You then set up a loop to iterate over the names. You request your user to enter a name and declare a variable to store it in. Next, you check to see if you had an error; if so, the program will exit with a panic. Because Scanln captures the entire input, including the carriage return, you need to remove any space from the input; you do this with the strings.TrimSpace function.

The if block checks whether the name is present in the map and prints feedback. If the name is present it then continues back to the top of the loop. If the name is not in the map, it provides feedback to the user and then will ask for a new username for the associated name. The program checks again to see if there is an error. With no error, it trims off the carriage return, assigns the username value to the name key, and then prints feedback that the data was updated.

Let’s run the program on the command line:

go run usernames.go

You’ll see the following output:

OutputEnter a name: Sammy "sammy-shark" is the username of "Sammy" Enter a name: Jesse I don't have Jesse's username, what is it? JOctopus Data updated. Enter a name:

When you’re done testing, press CTRL + C to escape the program.

This shows how you can modify maps interactively. With this particular program, as soon as you exit the program with CTRL + C you’ll lose all your data unless you implement a way to handle reading and writing files.

To summarize, you can add items to maps or modify values with the map[key] = value syntax.

Deleting Map Items

Just as you can add key-value pairs and change values within the map data type, you can also delete items within a map.

To remove a key-value pair from a map, you can use the built-in function delete(). The first argument is the map you are deleting from. The second argument is the key you are deleting:

delete(map, key)

Let’s define a map of permissions:

permissions := map[int]string{1: "read", 2: "write", 4: "delete", 8: "create", 16:"modify"}

You no longer need the modify permission, so you’ll remove it from your map. Then you’ll print out the map to confirm it was removed:

permissions := map[int]string{1: "read", 2: "write", 4: "delete", 8: "create", 16: "modify"} delete(permissions, 16) fmt.Println(permissions)

The output will confirm the deletion:

Outputmap[1:read 2:write 4:delete 8:create]

The line delete(permissions, 16) removes the key-value pair 16:"modify" from the permissions map.

If you would like to clear a map of all of its values, you can do so by setting it equal to an empty map of the same type. This will create a new empty map to use, and the old map will be cleared from memory by the garbage collector.

Let’s remove all the items within the permissions map:

permissions = map[int]string{} fmt.Println(permissions)

The output shows that you now have an empty map devoid of key-value pairs:

Outputmap[]

Because maps are mutable data types, they can be added to, modified, and have items removed and cleared.

Conclusion

This tutorial explored the map data structure in Go. Maps are made up of key-value pairs and provide a way to store data without relying on indexing. This allows us to retrieve values based on their meaning and relation to other data types.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us

Next in series: Understanding Arrays and Slices in Go ->Tutorial Series: How To Code in Go

Go (or GoLang) is a modern programming language originally developed by Google that uses high-level syntax similar to scripting languages. It is popular for its minimal syntax and innovative handling of concurrency, as well as for the tools it provides for building native binaries on foreign platforms.

GoDevelopmentBrowse Series: 53 articles1/53 How To Code in Go eBook 2/53 How To Install Go and Set Up a Local Programming Environment on Ubuntu 18.04 3/53 How To Install Go and Set Up a Local Programming Environment on macOS About the authorsDefault avatarGopher Guides

author

Default avatarKathryn Hancox

editor

Still looking for an answer?Ask a questionSearch for more helpWas this helpful? 1 Comments

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Sign In or Sign Up to CommentMichael Bøcker-Larsen • May 8, 2019

My I suggest to add an example on how you can emit types in literals, which is obvious for strings, but maybe not so obvious for structs.

It can greatly enhance your codes readability especially when using other peoples packages.

Here is an example https://play.golang.org/p/xEOqsY7nrv8

Now imagine that Thing map had been map[string]*dynamodb.AttributeValue

Creative CommonsThis work is licensed under a Creative Commons Attribution-NonCommercial- ShareAlike 4.0 International License.


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有